using UnityEngine;
using UnityEngine.UI;
using UnityEditor;
using System.Collections.Generic;
using System.IO;

public class TextureSearchTool : EditorWindow
{
    private string textureName = "";
    private string searchPath = "Assets";
    private Dictionary<string, List<string>> prefabMatches = new Dictionary<string, List<string>>();
    private Dictionary<string, bool> prefabFoldouts = new Dictionary<string, bool>();
    private string selectedPrefab = "";
    private Vector2 scrollPos;

    [MenuItem("GameTools/检测资源/纹理查找工具")]
    public static void ShowWindow()
    {
        GetWindow<TextureSearchTool>("Texture Search");
    }

    void OnGUI()
    {
        GUILayout.Label("Search Prefabs by Texture", EditorStyles.boldLabel);
        
        textureName = EditorGUILayout.TextField("Texture Name:", textureName);
        
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField("Search Path:", searchPath);
        if (GUILayout.Button("Select Folder", GUILayout.Width(100)))
        {
            searchPath = EditorUtility.OpenFolderPanel("Select Search Folder", "Assets", "");
            if (string.IsNullOrEmpty(searchPath))
            {
                searchPath = "Assets";
            }
            else if (!searchPath.Contains(Application.dataPath))
            {
                EditorUtility.DisplayDialog("Error", "Please select a folder under Assets", "OK");
                searchPath = "Assets";
            }
            else
            {
                searchPath = "Assets" + searchPath.Substring(Application.dataPath.Length);
            }
        }
        EditorGUILayout.EndHorizontal();
        
        if (GUILayout.Button("Search"))
        {
            SearchPrefabs();
        }

        GUILayout.Space(10);
        GUILayout.Label("Matched Prefabs:");
        
        scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
        foreach (var kvp in prefabMatches)
        {
            string prefabPath = kvp.Key;
            var matches = kvp.Value;
            
            var headerStyle = prefabPath == selectedPrefab ? 
                new GUIStyle(EditorStyles.foldout) { fontStyle = FontStyle.Bold } : 
                EditorStyles.foldout;
            
            if (!prefabFoldouts.ContainsKey(prefabPath))
                prefabFoldouts[prefabPath] = false;
            
            prefabFoldouts[prefabPath] = EditorGUILayout.Foldout(prefabFoldouts[prefabPath], prefabPath, headerStyle);
            
            if (GUILayoutUtility.GetLastRect().Contains(Event.current.mousePosition) && 
                Event.current.type == EventType.MouseDown)
            {
                Object obj = AssetDatabase.LoadAssetAtPath<Object>(prefabPath);
                if (obj != null)
                {
                    Selection.activeObject = obj;
                    EditorGUIUtility.PingObject(obj);
                    selectedPrefab = prefabPath;
                }
                Event.current.Use();
            }

            if (prefabFoldouts[prefabPath])
            {
                EditorGUI.indentLevel++;
                foreach (var nodePath in matches)
                {
                    if (GUILayout.Button(nodePath, EditorStyles.miniButton))
                    {
                        GameObject prefabObj = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
                        if (prefabObj != null && 
                            Selection.activeObject != null && 
                            Selection.activeObject.name == Path.GetFileNameWithoutExtension(prefabPath))
                        {
                            // First select the prefab instance to ensure we have the right context
                            Selection.activeObject = prefabObj;
                            EditorGUIUtility.PingObject(prefabObj);
                            
                            // Then find and select the specific node
                            Transform node = FindNodeByPath(Selection.activeGameObject, nodePath);
                            if (node != null)
                            {
                                // Force selection with delay
                                    Selection.activeGameObject = node.gameObject;
                            };
                        }
                    }
                }
                EditorGUI.indentLevel--;
            }
        }
        EditorGUILayout.EndScrollView();
    }

    void SearchPrefabs()
    {
        prefabMatches.Clear();
        prefabFoldouts.Clear();
        string[] allPrefabs = Directory.GetFiles(searchPath, "*.prefab", SearchOption.AllDirectories);

        foreach (string prefabPath in allPrefabs)
        {
            GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
            if (prefab != null)
            {
                var matches = FindMatchingNodes(prefab);
                if (matches.Count > 0)
                {
                    prefabMatches[prefabPath] = matches;
                }
            }
        }
        Repaint();
    }

    List<string> FindMatchingNodes(GameObject root)
    {
        List<string> matches = new List<string>();
        FindMatchingNodesRecursive(root, "", matches);
        return matches;
    }

    void FindMatchingNodesRecursive(GameObject go, string currentPath, List<string> matches)
    {
        string nodePath = string.IsNullOrEmpty(currentPath) ? go.name : currentPath + "/" + go.name;
        
        Image image = go.GetComponent<Image>();
        if (image != null && image.sprite != null && 
            image.sprite.texture != null && 
            image.sprite.texture.name == textureName)
        {
            matches.Add(nodePath);
        }

        foreach (Transform child in go.transform)
        {
            FindMatchingNodesRecursive(child.gameObject, nodePath, matches);
        }
    }

    Transform FindNodeByPath(GameObject root, string path)
    {
        try 
        {
            string[] parts = path.Split('/');
            Transform current = root.transform;
            
            // Start from index 0 to include root name
            for (int i = 0; i < parts.Length; i++)
            {
                if (current == null) return null;
                
                // Special case for root transform
                if (i == 0 && current.name == parts[i])
                    continue;
                    
                current = current.Find(parts[i]);
                if (current == null)
                {
                    Debug.LogWarning($"Cannot find node: {parts[i]} in path: {path}");
                    return null;
                }
            }
            return current;
        }
        catch (System.Exception e)
        {
            Debug.LogError($"Error finding node by path: {path}\n{e}");
            return null;
        }
    }
}
